#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    bool open = false ;

    this->setAttribute(Qt::WA_TranslucentBackground);
    ui->setupUi(this);

    this->setWindowFlags(Qt::FramelessWindowHint);

    QSizeGrip * gripper = new QSizeGrip(this);
    gripper->resize(8,8);
    ui->gripperlayout->addWidget(gripper);

    this->move(0,32);

    QObject::connect(ui->treeWidget , SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(UpdateCat(QTreeWidgetItem*,int)) ) ;
    QObject::connect(ui->listWidget,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(ProgramEntryDblClicked(QListWidgetItem*)));
    QObject::connect(ui->ExecButton,SIGNAL(clicked()),this,SLOT(ExecuteCommande()));
    QObject::connect(ui->SearchBox,SIGNAL(returnPressed()),this,SLOT(ExecuteCommande()));
    QObject::connect(ui->AsAdminButton,SIGNAL(clicked()),this,SLOT(PrependAdminCommande()));
    QObject::connect(ui->JoinFileButton,SIGNAL(clicked()),this,SLOT(JoinFileCommande()));
    QObject::connect(ui->ControlCenterLauncher,SIGNAL(clicked()),this,SLOT(LaunchControlCenter()));
    QObject::connect(ui->MyComputerLauncher,SIGNAL(clicked()),this,SLOT(LaunchMyComputer()));
    QObject::connect(ui->MyHomeLauncher,SIGNAL(clicked()),this,SLOT(LaunchMyHome()));
    QObject::connect(ui->NetworkLauncher,SIGNAL(clicked()),this,SLOT(LaunchNetwork()));
    QObject::connect(ui->PackageManagerLauncher,SIGNAL(clicked()),this,SLOT(LaunchPackageManager()));
    QObject::connect(ui->TrashLauncher,SIGNAL(clicked()),this,SLOT(LaunchMyTrash()));
    QObject::connect(ui->ShowMyFavoritesButton,SIGNAL(clicked()),this,SLOT(ShowMyFavorites()));

    QFile * thedbfile = new QFile(QDir::homePath() + "/.config/ModernDesktopEnvironment/applications.db");

    if ( !thedbfile->exists() )
    {
        qDebug() << "db not found, creating one ..." ;
        QFile *newemptydb =  new QFile (QCoreApplication::applicationDirPath() + "/data/applications.db");
        if (newemptydb->exists() )
        {
            bool copied = newemptydb->copy(QDir::homePath() + "/.config/ModernDesktopEnvironment/applications.db");
            if ( copied)
            {
                qDebug() << "ok done";
                QFile * file = new QFile(QDir::homePath() + "/.config/ModernDesktopEnvironment/applications.db");
                file->setPermissions(QFile::ReadOther | QFile::WriteOther | QFile::ExeOther);
            }
            else
            {
                qDebug() << "NEW DB FAILED !";
            }

            qDebug() << "opening db" ;
            QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
            db.setDatabaseName(QDir::homePath() + "/.config/ModernDesktopEnvironment/applications.db");

            if (!db.open())
            {
                QSqlError error = db.lastError() ;
                qDebug() << "erreur d'ouverture SQL" ;
                close() ;
            }
            else
            {
                open = true ;
            }

            qDebug() << "ok db opened" ;

            qDebug() << "filling new db" ;
            //GetListOfIcons();
            ParseApplications() ;
        }
        else
        {
            qDebug() << "FILE FOR COPYING DOES NOT EXIST !" ;
        }
    }


    if ( !open )
    {
        qDebug() << "opening db" ;
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(QDir::homePath() + "/.config/ModernDesktopEnvironment/applications.db");
        if (!db.open())
        {
            QSqlError error = db.lastError() ;
            qDebug() << "erreur d'ouverture SQL" ;
            close() ;
        }
        else
        {
            qDebug() << "parsing apps" ;
            ParseApplications() ;
        }
        qDebug() << "ok db opened" ;
    }

    model = new QSqlRelationalTableModel(this) ;
    model->setTable("APPLICATIONS");

    ui->listWidget->addAction(ui->actionAjouter_aux_favoris);
    ui->listWidget->addAction(ui->actionEditer);


    ShowMyFavorites();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::ParseApplications()
{

    QSqlDatabase::database().transaction();
    QSqlQuery query;
    qDebug() << "clearing all base...." ;
    query.exec(QString("DELETE FROM APPLICATIONS WHERE CAT_APP<>'MyFavourites';"));
    QSqlDatabase::database().commit();

    QList<QString> cat_list;
    cat_list.append("MyFavourites"); // favoris
    cat_list.append("Utility"); // accessoires
    cat_list.append("Office"); // bureautique
    cat_list.append("Network"); // web et reseau
    cat_list.append("AudioVideo"); // multimedia
    cat_list.append("Development"); // developpement
    cat_list.append("System"); // system
    cat_list.append("Game"); // jeux
    cat_list.append("Settings"); // préférences
    cat_list.append("Graphics"); // graphisme

    QStringList filter_list ;
    filter_list.append("*.desktop");

    QString lang = QLocale::system().name(); // (fr_FR)
    QString country = lang.section('_', 0, 0); // (fr_FR -> fr)
    QString locale_name = QString("Name").append("[").append(country).append("]").append("="); // Name[fr]

    QDirIterator desktop_iter( "/usr/share/applications/" , QDirIterator::Subdirectories | QDirIterator::FollowSymlinks );

    qDebug() << "main parsing loop ..." ;
    while (desktop_iter.hasNext())
    {
        desktop_iter.next(); // move to child directory

        QFile desktop_file(desktop_iter.filePath());

        QString name;
        QString exec;
        QString icon_name;
        QString icon_path;
        QString categories;
        QString full_path;
        QString args;
        QStringList split_path;
        QString app_name;
        bool scrsvr = false ;

        QString file_name = desktop_file.fileName();

        if (file_name == "." || file_name == "..")
            continue;

        if (!desktop_file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            qDebug() << "Problem to read .desktop file:" << file_name;
            continue;
        }

        QTextStream stream(&desktop_file);
        QString line;


        do
        {
            line = stream.readLine();
            bool ok = false ;

            if (! line.isNull() || ! line.isEmpty())
            {
                if (line.startsWith("Categories="))
                {
                    QString new_line = line.remove("Categories=");
                    QStringList split = new_line.split(";"); // get the single categories

                    for (int i = 0; i < split.size(); ++i)
                    {
                        if (cat_list.contains(split.at(i)))
                        {
                            categories = split.at(i); // get the category
                            ok = true ;
                            break;
                        }
                        if ( split.at(i) == "Screensaver" )
                        {
                            scrsvr = true ;
                            ok = true ;
                            break;
                        }
                    }
                    if ( ok == false )
                    {
                        categories = "Other" ;
                    }
                    qDebug() << "Categories:" << categories;
                }
                if (line.startsWith("Name="))
                {
                    name = line.remove("Name="); // default name
                    qDebug() << "Name:" << name;
                }
                if (line.startsWith(locale_name))
                {
                    name = line.remove(locale_name); // locale name
                    qDebug() << "Locale Name:" << name;
                }
                if (line.startsWith("Exec="))
                {
                    exec = line.remove("Exec=");
                    if (! exec.startsWith('/')) // full path not already set
                        exec.prepend("/usr/bin/");
                    qDebug() << "Exec:" << exec;
                }
                if (line.startsWith("Icon="))
                {
                    icon_name = line.remove("Icon=");
                    qDebug() << "Icon:" << icon_name;
                }
            }
        }
        while (!line.isNull());

        if (! exec.isEmpty() && ! categories.isEmpty() && ! name.isEmpty() && ! icon_name.isEmpty())
        {
            full_path = exec.section(' ', 0, 0); // remove eventually args after app name (/usr/bin/vlc %U -> /usr/bin/vlc)
            qDebug() << "full_path:" << full_path;
            args = exec.section(' ', 1, 1); // save args after app name with space (/usr/bin/vlc %U -> _%U)

//            if (args.startsWith('-')) // leave only args i.e. for OpenOffice (soffice-writer)
//                qDebug() << "args:" << args;
//            else
//                args.clear();

            QString cleanargs = " " ;
            QStringList arglst = args.split(" "); // get the single args

            for (int i = 0; i < arglst.size(); ++i)
            {
                QString thearg = arglst.at(i) ;
                if ( !thearg.startsWith('%') )
                {
                    cleanargs = cleanargs + " " + thearg ;
                }
            }

            QString thegoodpath = full_path + cleanargs ;

//            split_path = full_path.split('/', QString::SkipEmptyParts); // (/usr/bin/vlc -> usr, bin, vlc)
//            qDebug() << "split_path:" << split_path;
//            app_name = split_path.last(); // (usr, bin, vlc -> vlc)
//            qDebug() << "App_name:" << app_name;

            icon_path = FindBestIcon(icon_name);

            if ( name.length() > 0 && !scrsvr)
            {
                QSqlDatabase::database().transaction();
                QSqlQuery query;
                qDebug() << "adding line for app" ;
                query.exec(QString("INSERT INTO APPLICATIONS('ICO_APP','NOM_APP','CAT_APP','EXE_APP') VALUES('%1','%2','%3','%4');").arg(icon_path).arg(name).arg(categories).arg(thegoodpath));
                QSqlDatabase::database().commit();
            }
        }
    }
    qDebug() << "ok all .desktop parsed !" ;
}

// Find the best icon with highest resolution for the launcher
QString MainWindow::FindBestIcon ( QString icon )
{
    QString searched_icon = icon ;

    if (searched_icon.length() == 0 )
    {
        qDebug() << "no icon set" ;
        searched_icon = "application-default-icon" ;
    }

    if (searched_icon.startsWith('/'))
    {
        qDebug() << "full path already set, return it" ;
        return searched_icon ;
    }

    QStringList iconbase ;
    iconbase << "gnome-colors-common" << "hicolor" << "gnome" ;

    QString iconpath = "/usr/share/icons/" ;

    QStringList sizelist ;
    sizelist << "128x128" << "64x64" << "48x48" << "32x32" << "'24x24" ;

    QStringList categorylist ;
    categorylist << "apps" << "devices" << "categories" << "filesystems" << "places" << "actions" ;

    QStringList extensionlist ;
    extensionlist << "png" << "xpm" ;

    QString foundiconfile ;
    QStringList iconimagelist ;

    foreach ( QString extension , extensionlist )
    {
        if ( searched_icon.indexOf ( QString(".%1").arg(extension) ) != -1 )
        {
            qDebug() << "removing extension" ;
            searched_icon = searched_icon.replace ( QString(".%1").arg(extension) , QString() ) ;
        }
    }

    foreach ( QString size , sizelist )
    {
        foreach ( QString extension , extensionlist )
        {
            foreach ( QString category , categorylist )
            {
                foreach ( QString iconbasecat , iconbase )
                {
                    qDebug() << "adding entry to stringlist" ;
                    QString iconfile = QString ("%1/%2/%3/%4/%5.%6").arg(iconpath).arg(iconbasecat).arg(size).arg(category).arg(searched_icon).arg(extension) ;
                    iconimagelist.append(iconfile) ;
                }
            }
        }
    }

    foreach ( QString extension , extensionlist )
    {
        qDebug() << "searching in icons" ;
        QString iconfile = QString ("/usr/share/icons/%1.%2").arg(searched_icon).arg(extension) ;
        iconimagelist.append(iconfile) ;
    }

    foreach ( QString extension , extensionlist )
    {
        qDebug() << "searching in pixmaps" ;
        QString iconfile = QString ("/usr/share/pixmaps/%1.%2").arg(searched_icon).arg(extension) ;
        iconimagelist.append(iconfile) ;
    }

    qDebug() <<  "looking in stringlist after icon path..." ;
    foreach ( QString iconimage , iconimagelist )
    {
        if ( QFile(iconimage).exists() )
        {
            foundiconfile = iconimage ;
            qDebug() << "Found: " << foundiconfile << ", return it" ;
            return foundiconfile ;
        }
    }

    qDebug() << "none was found, search for fallback icon..." ;
    iconimagelist.clear();
    QString fallback_icon = "application-default-icon";
    foreach ( QString size , sizelist )
    {
        foreach ( QString extension , extensionlist )
        {
            foreach ( QString category , categorylist )
            {
                foreach ( QString iconbasecat , iconbase )
                {
                    qDebug() << "adding entry to list" ;
                    QString iconfile = QString ("%1/%2/%3/%4/%5.%6").arg(iconpath).arg(iconbasecat).arg(size).arg(category).arg(fallback_icon).arg(extension) ;
                    iconimagelist.append(iconfile) ;
                }
            }
        }
    }
    foreach ( QString extension , extensionlist )
    {
        qDebug() << "searching in icons" ;
        QString iconfile = QString ("/usr/share/icons/%1.%2").arg(fallback_icon).arg(extension) ;
        iconimagelist.append(iconfile) ;
    }
    foreach ( QString iconimage , iconimagelist )
    {
        if ( QFile(iconimage).exists() )
        {
            qDebug() <<  "searching default icon in list" ;
            foundiconfile = iconimage ;
            qDebug() << "Found: " << foundiconfile << ", return it" ;
            return foundiconfile ;
        }
    }
    return "" ;
}




void MainWindow::UpdateCat( QTreeWidgetItem* theitem ,int col )
{
    cat = theitem->toolTip(col) ;
    qDebug() << "categorie :" << cat ;


    QSqlDatabase::database().transaction();
    QSqlQuery query;
    qDebug() << "getting all apps for categorie :"  << cat ;
    query.exec(QString("SELECT * FROM APPLICATIONS WHERE CAT_APP='%1';").arg(cat));
    QSqlDatabase::database().commit();

    ui->listWidget->clear();

    qDebug() << "just before loop :" ;
    forever
    {
        if ( query.next() )
        {
            QListWidgetItem *theentry =  new QListWidgetItem(QIcon (query.value(model->fieldIndex("ICO_APP")).toString()),query.value(model->fieldIndex("NOM_APP")).toString(),ui->listWidget) ;
            theentry->setToolTip(query.value(model->fieldIndex("ID_APP")).toString()) ;
            qDebug() << " new theentry creeated ... ok" ;
            ui->listWidget->addItem(theentry) ;
            qDebug() << " item added to list  ... ok " ;
        }
        else
        {
            break;
        }
    }
    qDebug() << "just after loop :" ;
}

void MainWindow::ShowMyFavorites()
{
    cat = "Fav" ;

    ui->treeWidget->clearSelection();
    QSqlDatabase::database().transaction();
    QSqlQuery query;
    qDebug() << "getting all favorites apps"  ;
    query.exec("SELECT * FROM APPLICATIONS WHERE CAT_APP='MyFavourites';");
    QSqlDatabase::database().commit();

    ui->listWidget->clear();

    qDebug() << "just before loop :" ;
    forever
    {
        if ( query.next() )
        {
            QListWidgetItem *theentry =  new QListWidgetItem(QIcon (query.value(model->fieldIndex("ICO_APP")).toString()),query.value(model->fieldIndex("NOM_APP")).toString(),ui->listWidget) ;
            theentry->setToolTip(query.value(model->fieldIndex("ID_APP")).toString()) ;
            qDebug() << " new theentry creeated ... ok" ;
            ui->listWidget->addItem(theentry) ;
            qDebug() << " item added to list  ... ok " ;
        }
        else
        {
            break;
        }
    }
    qDebug() << "just after loop :" ;

}

void MainWindow::ProgramEntryDblClicked(QListWidgetItem * entry)
{
    int id = entry->toolTip().toInt();

    QSqlDatabase::database().transaction();
    QSqlQuery query;
    qDebug() << "getting info form entry dbl clicked ..." ;
    query.exec(QString("SELECT * FROM APPLICATIONS WHERE ID_APP='%1';").arg(id));
    QSqlDatabase::database().commit();

    if ( query.next() )
    {
        QString command = query.value(model->fieldIndex("EXE_APP")).toString() ;
        qDebug() << "executable clické :" << command ;
        QProcess::startDetached ( command ) ;
    }

    ui->listWidget->clearSelection();

}

void MainWindow::ExecuteCommande()
{
    QProcess::startDetached(ui->SearchBox->text()) ;
    ui->SearchBox->clear();
}

void MainWindow::PrependAdminCommande()
{
    ui->SearchBox->setText(ui->SearchBox->text().prepend("gksu ")) ;
}

void MainWindow::JoinFileCommande()
{
    QString fileName = QFileDialog::getOpenFileName( this , tr ("Ajouter un fichier ...") , QDir::homePath ( ) , tr ("Tous (*.*)") ) ;

    ui->SearchBox->setText(ui->SearchBox->text().append(QString(" \"%1\"").arg(fileName))) ;
}

void MainWindow::LaunchPackageManager()
{
    QProcess::startDetached("gpk-application") ;
}

void MainWindow::LaunchControlCenter()
{
    QProcess::startDetached("gnome-control-center") ;
}

void MainWindow::LaunchNetwork()
{
    QProcess::startDetached("nautilus --no-desktop network:") ;
}

void MainWindow::LaunchMyComputer()
{
    QProcess::startDetached("nautilus --no-desktop computer:") ;
}

void MainWindow::LaunchMyHome()
{
    QProcess::startDetached(QString("nautilus %1").arg(QDir::homePath())) ;
}

void MainWindow::LaunchMyTrash()
{
    QProcess::startDetached("nautilus --no-desktop trash:") ;
}

void MainWindow::on_actionAjouter_aux_favoris_triggered()
{
    if ( ui->listWidget->currentItem() >= 0 )
    {
        int id = ui->listWidget->currentItem()->toolTip().toInt();
        QSqlDatabase::database().transaction();
        QSqlQuery query;
        query.exec(QString("SELECT * FROM APPLICATIONS WHERE ID_APP='%1';").arg(id));
        QSqlDatabase::database().commit();
        QString exe_app ;
        QString ico_app ;
        QString nom_app ;
        if ( query.next() )
        {
            exe_app = query.value(model->fieldIndex("EXE_APP")).toString() ;
            ico_app = query.value(model->fieldIndex("ICO_APP")).toString() ;
            nom_app = query.value(model->fieldIndex("NOM_APP")).toString() ;
        }
        QString cat_app = QString("MyFavourites") ;

        qDebug() << "setting new favorites app"  ;
        query.exec(QString("INSERT INTO APPLICATIONS('ICO_APP','NOM_APP','CAT_APP','EXE_APP') VALUES('%1','%2','%3','%4');").arg(ico_app).arg(nom_app).arg(cat_app).arg(exe_app));
        QSqlDatabase::database().commit();
    }
}

void MainWindow::on_actionEditer_triggered()
{
     if ( ui->listWidget->currentItem() >= 0 )
    {
        int id = ui->listWidget->currentItem()->toolTip().toInt();
        QSqlDatabase::database().transaction();
        QSqlQuery query;
        qDebug() << "loading param for edit"  ;
        query.exec(QString("SELECT * FROM APPLICATIONS WHERE ID_APP='%1';").arg(id));
        QSqlDatabase::database().commit();

        save_id = id ;

        QString exe_app ;
        QString ico_app ;
        QString nom_app ;

        if ( query.next() )
        {
            exe_app = query.value(model->fieldIndex("EXE_APP")).toString() ;
            ico_app = query.value(model->fieldIndex("ICO_APP")).toString() ;
            nom_app = query.value(model->fieldIndex("NOM_APP")).toString() ;
        }

        editwin      = new QMainWindow;
        central      = new QWidget(editwin);
        layout       = new QGridLayout(central);
        nom_box      = new QLineEdit(nom_app,central);
        label1       = new QLabel("Nom du programme",central) ;
        exe_box      = new QLineEdit(exe_app,central);
        label2       = new QLabel("Chemin programme",central) ;
        ico_box      = new QLineEdit(ico_app,central);
        label3       = new QLabel("Icone programme",central) ;
        cancelbutton = new QPushButton("Annuler",central);
        validbutton  = new QPushButton("Valider",central) ;

        layout->addWidget(label1 ,0,0);
        layout->addWidget(nom_box,0,1);
        layout->addWidget(label2 ,1,0);
        layout->addWidget(exe_box,1,1);
        layout->addWidget(label3 ,2,0);
        layout->addWidget(ico_box,2,1);
        layout->addWidget(cancelbutton,4,0);
        layout->addWidget(validbutton,4,1);

         editwin->setCentralWidget(central);

         editwin->resize(600,150);

         editwin->show();

         connect(cancelbutton,SIGNAL(clicked()),editwin,SLOT(close()));
         connect(validbutton,SIGNAL(clicked()),this,SLOT(SaveModif()));


    }
}

void MainWindow::SaveModif()
{
    QSqlDatabase::database().transaction();
    QSqlQuery query;
    qDebug() << "saving change in database app : "  ;
    int id = save_id ;
    QString ico = ico_box->text() ;
    QString exe = exe_box->text() ;
    QString nom = nom_box->text() ;
    qDebug() << "id : " << id  ;
    qDebug() << "nom : " << nom ;
    qDebug() << "exec : " << exe ;
    qDebug() << "ico : " << ico ;
    query.exec(QString("UPDATE APPLICATIONS SET NOM_APP='%1' , EXE_APP='%2' , ICO_APP='%3' WHERE ID_APP='%4' ;").arg(nom).arg(exe).arg(ico).arg(id));
    QSqlDatabase::database().commit();
    editwin->close();
    RefreshCat();
}

void MainWindow::RefreshCat( )
{
    qDebug() << "categorie :" << cat ;

    if ( cat == "Fav" )
    {
        ShowMyFavorites();
    }
    else
    {
        QSqlDatabase::database().transaction();
        QSqlQuery query;
        qDebug() << "getting all apps for categorie :"  << cat ;
        query.exec(QString("SELECT * FROM APPLICATIONS WHERE CAT_APP='%1';").arg(cat));
        QSqlDatabase::database().commit();

        ui->listWidget->clear();

        qDebug() << "just before loop :" ;
        forever
        {
            if ( query.next() )
            {
                QListWidgetItem *theentry =  new QListWidgetItem(QIcon (query.value(model->fieldIndex("ICO_APP")).toString()),query.value(model->fieldIndex("NOM_APP")).toString(),ui->listWidget) ;
                theentry->setToolTip(query.value(model->fieldIndex("ID_APP")).toString()) ;
                qDebug() << " new theentry creeated ... ok" ;
                ui->listWidget->addItem(theentry) ;
                qDebug() << " item added to list  ... ok " ;
            }
            else
            {
                break;
            }
        }
        qDebug() << "just after loop :" ;
    }

}







